package com.foo.common.base.utils;

import static org.junit.Assert.assertTrue;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.nio.charset.Charset;
import java.security.SecureRandom;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.DecimalFormat;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.persistence.Column;
import javax.persistence.Table;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.configuration2.Configuration;
import org.apache.commons.configuration2.builder.fluent.Configurations;
import org.apache.commons.configuration2.ex.ConfigurationException;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.filefilter.FileFilterUtils;
import org.apache.commons.io.filefilter.TrueFileFilter;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.SystemUtils;
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;

import com.foo.common.base.enums.FormFieldValidation;
import com.foo.common.base.pojo.CommonPatchRelease;
import com.foo.common.base.utils.laboratory.FooUtilsFomulaHelper;
import com.github.mustachejava.DefaultMustacheFactory;
import com.github.mustachejava.Mustache;
import com.github.mustachejava.MustacheFactory;
import com.google.common.base.CaseFormat;
import com.google.common.base.Charsets;
import com.google.common.base.Joiner;
import com.google.common.base.MoreObjects;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.io.Files;
import com.google.common.io.LineProcessor;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import sun.misc.BASE64Decoder;

public class FooUtils {

	private final static String DES = "DES";
	private final static String key = "x!%^&2azdd";
	public final static String ddl_form_field_type_textarea = "textarea";
	public final static String ddl_form_field_type_text = "text";
	public final static String ddl_int_default_zero = "INT default 0";
	public final static int ddl_pk_length = 36;// uuid2模式下，36是标准的id长度
	public final static int ddl_textarea_length = 2000;// 长文本的长度
	public final static String global_test_dir = "d:\\tmp\\test";
	public final static String global_test_file_working_directory_str = "d:\\tmp\\test";

	public final static File global_test_file_working_directory = new File(
			global_test_file_working_directory_str);

	private static Configuration configuration;

	public final static String GIT_BASE_DIRECTORY = "D:\\tools\\myGit";

	public static Gson getGson() {
		Gson gson = new GsonBuilder().disableHtmlEscaping().serializeNulls()
				.setDateFormat("yyyy-MM-dd HH:mm:ss").create();
		return gson;
	}

	public static boolean isProjectSupportJdk8() {
		try {
			Sets.newConcurrentHashSet();
			return true;
		} catch (Exception e) {
			return false;
		}
	}

	public static void main(String[] args) throws Exception {
		logger.info("set is:{}", getGlobalArtifactId());
	}

	public static String toJson(Object object) {
		return getGson().toJson(object);
	}

	public final static String getGlobalArtifactId() {
		final String propertyName = "artifactId";
		final String s = getGlobalProperties().getString(propertyName);
		Preconditions.checkNotNull(s, "Please config:[" + propertyName
				+ "] in file:[global-config.properties]");
		return s;
	}

	public final static String getMvnBash() {
		final String propertyName = "mvnBash";
		final String s = getGlobalProperties().getString(propertyName);
		Preconditions.checkNotNull(s, "Please config:[" + propertyName
				+ "] in file:[global-config.properties]");
		return s;
	}

	public final static String getGitHome() {
		final String propertyName = "gitHome";
		final String s = getGlobalProperties().getString(propertyName);
		Preconditions.checkNotNull(s, "Please config:[" + propertyName
				+ "] in file:[global-config.properties]");
		return s;
	}

	public static void copyDirectory(String srcDirPath, String targetDirPath)
			throws Exception {
		if (IsMacOs()) {
			Process p = executeCommand(
					" cp -r " + srcDirPath + " " + targetDirPath + " ");
			StringWriter sWriterSuccess = new StringWriter();
			IOUtils.copy(p.getInputStream(), sWriterSuccess, "utf-8");
		} else {
			FileUtils.copyDirectory(new File(srcDirPath),
					new File(targetDirPath));
		}
	}

	public final static Configuration getGlobalProperties() {

		if (configuration != null) {
			return configuration;
		}
		final String globalConfigPropertiesFileName = "global-config.properties";

		Configurations configs = new Configurations();
		try {
			configuration = configs
					.properties(new File(globalConfigPropertiesFileName));
		} catch (ConfigurationException e) {
			logger.error("ConfigurationException:{}", e);
			configuration = null;
		}
		if (configuration == null) {
			throw new RuntimeException("Read configuration of:【"
					+ globalConfigPropertiesFileName + "】 error.");
		}
		return configuration;
	}

	/**
	 * 该方法的意义在于返回一个自定义的消息。即ret=-1
	 * 
	 * @param response
	 */
	public static void printJsonFromMap(HttpServletResponse response,
			Map<String, Object> myResultMap) {
		try {
			Gson gson = new GsonBuilder().disableHtmlEscaping().serializeNulls()
					.setDateFormat("yyyy-MM-dd HH:mm:ss").create();
			response.setCharacterEncoding(Charsets.UTF_8.toString());
			response.setContentType("text/plain");
			response.getWriter().write(gson.toJson(myResultMap));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 该方法的意义在于返回一个成功的消息。即ret=0
	 * 
	 * @param response
	 */
	public static void printSuccessJson(HttpServletResponse response) {
		Map<String, Object> myResultMap = Maps.newHashMap();
		myResultMap.put("ret", 0);
		myResultMap.put("msg", "");
		printJsonFromMap(response, myResultMap);
	}

	public static String getSeparateLine() {
		return "------------------------------------------------------------------------";
	}

	public static File getTestDirectory() {
		return global_test_file_working_directory;
	}

	public static int getInteger(Object object, int defaultInteger) {
		if (isInteger(object))
			return Integer.valueOf(object + "");
		else
			return defaultInteger;
	}

	public static String extractIntegerFromString(String object) {
		return object.replaceFirst(".*?(\\d+).*", "$1");
	}

	public static String getString(Object object) {
		return Strings
				.nullToEmpty(MoreObjects.firstNonNull(object, "").toString());
	}

	public static boolean isInteger(Object code) {
		if (code == null) {
			return false;
		}
		Pattern pattern = Pattern.compile("\\d+");
		Matcher isNum = pattern.matcher(code.toString());
		return isNum.matches();
	}

	public static int getDirectoryFilesNumber(File myDirectory)
			throws FileSystemException {

		Preconditions.checkArgument(myDirectory.isDirectory(),
				"you should passed in directory here.");

		List<File> files = (List<File>) FileUtils.listFiles(myDirectory,
				TrueFileFilter.TRUE, TrueFileFilter.TRUE);

		return files.size();

	}

	/**
	 * 统计目录下的所有文件数目和文件夹数目,并且打印文件或者目录的名称
	 * 
	 * @param myDirectory
	 * @throws FileSystemException
	 */
	public static void printDirectoryFilesAndDirs(File myDirectory)
			throws FileSystemException {

		Preconditions.checkArgument(myDirectory.isDirectory(),
				"you should passed in directory here.");

		List<File> files = (List<File>) FileUtils.listFiles(myDirectory,
				TrueFileFilter.TRUE, TrueFileFilter.TRUE);
		List<File> folders = (List<File>) FileUtils.listFilesAndDirs(
				myDirectory, FileFilterUtils.directoryFileFilter(),
				TrueFileFilter.TRUE);

		logger.info("Contains: {} files, {} folders.", files.size(),
				folders.size());
		logger.trace("Contains: files:{}", files.toString());
		logger.trace("Contains: directorys:{}", folders.toString());
	}

	/**
	 * 最简单的日志输出，用于调试j2se的简单程序
	 * 
	 * @return
	 */
	public static Logger getRootLogger() {
		return LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
	}

	public static File getTestJavaFile() {
		return FileUtils.getFile(global_test_file_working_directory,
				"test.java");
	}

	public static File getTestMavenPomFile() {
		return FileUtils.getFile(global_test_file_working_directory, "pom.xml");
	}

	public static File getTestHtmlFile() {
		return FileUtils.getFile(global_test_file_working_directory,
				"test.html");
	}

	public static File getTestLogFile() {
		return FileUtils.getFile(global_test_file_working_directory, "log.txt");
	}

	public static File getTestExcel2003File() {
		return FileUtils.getFile(global_test_file_working_directory,
				"test.xls");
	}

	public static File getUpdatePatchListTxtFile() {
		return FileUtils.getFile(global_test_file_working_directory,
				"updatePatchList.txt");
	}

	public static <T> void pretyPrint(Iterable<T> myList) {
		logger.info("Iterable your list now as result following:");
		logger.info(
				"*************************************************************");
		for (T t : myList) {
			logger.info("{}", t);
		}
	}

	public static String getPackageInfoFromJavaFile(File file)
			throws IOException {

		if (file == null) {
			logger.info("using test file");
			file = getTestJavaFile();
		}

		String myTargetDesStr = Files.readLines(file, Charsets.UTF_8,
				new LineProcessor<String>() {
					private String myTargetLineStr = "";

					@Override
					public boolean processLine(String line) throws IOException {
						if (line.contains("package")) {
							myTargetLineStr = line.replace("package", "")
									.replace(";", "").trim().replace(".", "/");
							return false;
						}
						return true;
					}

					@Override
					public String getResult() {
						return myTargetLineStr;
					}
				});
		return myTargetDesStr;
	}

	public static String firstCharToUpperCase(String str) {
		return Character.toUpperCase(str.charAt(0)) + str.substring(1);
	}

	final static Logger logger = LoggerFactory.getLogger("common");

	public static void info(String message, Object... object) {
		logger.info(message, object);
	}

	public static void printDivider() {
		System.out.println("--------------------------------------------");
	}

	public static void printList(List<?> list) {
		for (Object string : list) {
			System.out.println(string);
		}
	}

	public static String listToString(List<String> list) {
		return Joiner.on(",").join(list);
	}

	public static String parseMagnetStr(String source) {
		int magnetProtocolLength = 60;

		int x = source.indexOf("magnet:?xt=", 0);

		if (x == -1) {
			System.out.print("No magnet exist，reutrn");
			return "";
		}
		return source.substring(x, x + magnetProtocolLength);

	}

	public static void batchUpdate(List<String> updateSqlList,
			Connection jdbcCon) {
		Statement stmt = null;
		try {
			jdbcCon.setAutoCommit(false);
			stmt = jdbcCon.createStatement();
			for (String sql : updateSqlList) {
				stmt.addBatch(sql);
			}
			stmt.executeBatch();
			jdbcCon.commit();
		} catch (SQLException e) {
			info(" execute batchUpdate " + FooUtils.class.getName()
					+ " error:error sql list" + updateSqlList);
		} finally {
			stmt = null;
		}
	}

	/**
	 * 转化为年到秒的时间格式
	 * 
	 * @param dateTime
	 * @return
	 */
	public static String toDateFromYear2Second(DateTime dateTime) {
		return dateTime.toString("yyyy-MM-dd HH:mm:ss");
	}

	/**
	 * 转化为年到秒的时间格式
	 * 
	 * @param date
	 * @return
	 */
	public static Date toDateFromYear2Second(String date) {
		return DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")
				.parseDateTime(date).toDate();
	}

	/**
	 * 转化为年到天的时间格式
	 * 
	 * @param dateTime
	 * @return
	 */
	public static String toDateFromYear2Day(DateTime dateTime) {
		return dateTime.toString("yyyy-MM-dd");
	}

	/**
	 * 转化为年到天的时间格式
	 * 
	 * @param date
	 * @return
	 */
	public static Date toDateFromYear2Day(String date) {
		return DateTimeFormat.forPattern("yyyy-MM-dd").parseDateTime(date)
				.toDate();
	}

	/**
	 * 转化为年到分钟的时间格式
	 * 
	 * @param dateTime
	 * @return
	 */
	public static String toDateFromYear2Minute(DateTime dateTime) {
		return dateTime.toString("yyyy-MM-dd HH:mm");
	}

	/**
	 * 转化为年到分钟的时间格式
	 * 
	 * @param date
	 * @return
	 */
	public static Date toDateFromYear2Minute(String date) {
		return DateTimeFormat.forPattern("yyyy-MM-dd HH:mm").parseDateTime(date)
				.toDate();
	}

	/**
	 * 读入HttpServletResponse,输出失败的Json字符串到前台,全浏览器兼容
	 * 
	 * @param response
	 * @throws IOException
	 */
	public static void printJsonSuccessMsg(HttpServletResponse response)
			throws IOException {
		response.setCharacterEncoding(Charsets.UTF_8.toString());
		response.setContentType("text/plain");
		response.getWriter().write(
				new Gson().toJson(new ImmutableMap.Builder<String, String>()
						.put("success", "true").put("msg", "ok").build()));
	}

	public static void printJsonMessage(HttpServletResponse response,
			String message) throws IOException {
		response.setCharacterEncoding(Charsets.UTF_8.toString());
		response.setContentType("text/plain");
		response.getWriter()
				.write(new Gson()
						.toJson(new ImmutableMap.Builder<String, String>()
								.put("success", "true").put("msg", "ok")
								.put("message", message).build()));
	}

	/**
	 * 读入HttpServletResponse,将Json格式写出对象到HttpServletResponse
	 * 
	 * 只传一个参数将直接把对象写出到HttpServletResponse， 传二个参数则会把对象以键值对的方式写出到HttpServletResponse，
	 * 
	 * @param response
	 * @param object
	 *            ,可变参数，限制于2个参数之内
	 * @throws IOException
	 */
	public static void printJsonObject(HttpServletResponse response,
			Object... object) throws IOException {
		boolean myObjectLength = object.length >= 1 && object.length <= 2;
		Preconditions.checkArgument(myObjectLength,
				"Object Length should be between 1 and 2");
		response.setCharacterEncoding(Charsets.UTF_8.toString());
		response.setContentType("text/plain");
		Map<String, Object> myResultMap = Maps.newHashMap();
		myResultMap.put("success", "true");
		myResultMap.put("msg", "ok");
		if (object.length == 2) {
			myResultMap.put(object[0].toString(), object[1]);
			response.getWriter().write(new Gson().toJson(myResultMap));
		} else {
			response.getWriter().write(new Gson().toJson(object[0]));
		}
	}

	public static <T> T getObject_Itms(Connection conn, Class<T> metaClazz,
			String searchSql) {
		PreparedStatement st = null;
		ResultSet rs = null;
		T myObject = null;
		try {
			st = conn.prepareStatement(searchSql.toString());
			rs = st.executeQuery();
			Object myColoumnObjectValue = null;

			while (rs.next()) {
				myObject = metaClazz.newInstance();
				// Refactor all fields and invoke method
				for (Field myField : metaClazz.getDeclaredFields()) {
					if (myField.isAnnotationPresent(Column.class)) {
						PropertyDescriptor pd = new PropertyDescriptor(
								myField.getName(), metaClazz);
						Method wM = pd.getWriteMethod();
						try {
							if (myField.getType().getName()
									.equals("java.util.Date")) {
								myColoumnObjectValue = MoreObjects
										.firstNonNull(
												rs.getTimestamp(myField
														.getAnnotation(
																Column.class)
														.name()),
												new Date());
							} else if (myField.getType().getName()
									.equals("java.lang.String")) {
								myColoumnObjectValue = Strings
										.nullToEmpty(
												rs.getString(myField
														.getAnnotation(
																Column.class)
														.name()));
							} else if (myField.getType().getName()
									.equals("int")) {
								myColoumnObjectValue = rs.getInt(myField
										.getAnnotation(Column.class).name());
							} else {
								info("warnUnmarkFieldType"
										+ myField.getType().toString());
							}
							wM.invoke(myObject, myColoumnObjectValue);
						} catch (SQLException e) {
							// log("fail on field" + myField.getName());
						}
					}
				}
				break;
			}
			conn.commit();
			rs.close();
			st.close();
		} catch (Exception e) {
			e.printStackTrace();
			info(" execute FooUtils error:error sql is: " + searchSql
					+ " error is" + e.getCause().toString());
		} finally {
		}
		return myObject;
	}

	public static <T> List<T> getObjects_Itms(Connection conn,
			Class<T> metaClazz, String nativeSql) {

		logger.info("executeSql:{}", nativeSql);
		List<T> myList = Lists.newArrayList();

		if (!metaClazz.isAnnotationPresent(Table.class)) {
			info("TableAnnotationDoNotPresent");
			return myList;
		}

		PreparedStatement st = null;
		ResultSet rs = null;
		T myObject = null;
		try {
			st = conn.prepareStatement(nativeSql.toString());
			rs = st.executeQuery();
			Object myColoumnObjectValue = null;

			while (rs.next()) {
				myObject = metaClazz.newInstance();
				// Refactor all fields and invoke method
				for (Field myField : metaClazz.getDeclaredFields()) {
					if (myField.isAnnotationPresent(Column.class)) {
						PropertyDescriptor pd = new PropertyDescriptor(
								myField.getName(), metaClazz);
						Method wM = pd.getWriteMethod();
						try {
							if (myField.getType().getName()
									.equals("java.util.Date")) {
								myColoumnObjectValue = MoreObjects
										.firstNonNull(
												rs.getTimestamp(myField
														.getAnnotation(
																Column.class)
														.name()),
												new Date());
							} else if (myField.getType().getName()
									.equals("java.lang.String")) {
								myColoumnObjectValue = Strings
										.nullToEmpty(
												rs.getString(myField
														.getAnnotation(
																Column.class)
														.name()));
							} else if (myField.getType().getName()
									.equals("int")) {
								myColoumnObjectValue = rs.getInt(myField
										.getAnnotation(Column.class).name());
							} else {
								info("warnUnmarkFieldType"
										+ myField.getType().toString());
							}
							wM.invoke(myObject, myColoumnObjectValue);
						} catch (SQLException e) {
							// log("fail on field" + myField.getName());
						}
					}
				}
				myList.add(myObject);
			}
			conn.commit();
			rs.close();
			st.close();
		} catch (Exception e) {
			e.printStackTrace();
			info("executeSql_Error:{}", nativeSql);
		} finally {
		}
		return myList;
	}

	/**
	 * 
	 * 读入HttpServletResponse,将Json格式写出对象到HttpServletResponse 此方法能够序列化null字段 只传一个参数将直接把对象写出到HttpServletResponse ，传二个参数则会把对象以键值对的方式写出到HttpServletResponse，
	 * 
	 * @author Liuchang
	 * @since Dec,2011
	 * 
	 * @param response
	 * @param object
	 *            ,可变参数，限制于2个参数之内
	 * @throws IOException
	 */
	public static void printJsonObjectSerializeNulls(
			HttpServletResponse response, Object... object) throws IOException {
		boolean myObjectLength = object.length >= 1 && object.length <= 2;
		Preconditions.checkArgument(myObjectLength,
				"Object Length should be between 1 and 2");
		response.setCharacterEncoding(Charsets.UTF_8.toString());
		Map<String, Object> myResultMap = Maps.newHashMap();
		response.setContentType("text/plain");
		myResultMap.put("success", "true");
		myResultMap.put("msg", "ok");
		// serializeNulls 序列化null字段
		Gson gson = new GsonBuilder().serializeNulls()
				.excludeFieldsWithoutExposeAnnotation().create();
		if (object.length == 2) {
			myResultMap.put(object[0].toString(), object[1]);
			response.getWriter().write(gson.toJson(myResultMap));
		} else {
			response.getWriter().write(gson.toJson(object[0]));
		}
	}

	/**
	 * 如果列表不为空，那么返回列表本身；如果列表为空，则返回空列表
	 */
	public static <T> List<T> nullToEmpty(List<T> list) {
		if (list != null && list.size() > 0) {
			return list;
		} else {
			return Lists.newArrayList();
		}
	}

	public static String formatDouble(String result) {
		return String.format("%1$.2f", Double.parseDouble(result));
	}

	public static String formatDouble(double result) {
		return String.format("%1$.2f", result);
	}

	/**
	 * 判定是否是数字
	 * 
	 * @param code
	 *            例如：12.23
	 * @return
	 */
	public static boolean isNum(String code) {
		Pattern pattern = Pattern.compile("\\d+(\\.\\d+)?");
		Matcher isNum = pattern.matcher(code);
		return isNum.matches();
	}

	/**
	 * 判断是否是字符
	 * 
	 * @param code
	 * @return
	 */
	public static boolean isCharacter(String code) {
		Pattern pattern = Pattern.compile("[A-Za-z]*");
		Matcher isNum = pattern.matcher(code);
		return isNum.matches();
	}

	/**
	 * @param myFormula
	 *            :传入的公式，四则表达式（即加减乘除），结果保存小数点后2位
	 * @param argumentMap
	 *            : 键(key)：变量名;值(value)：变量值
	 * 
	 * @throws IllegalArgumentException
	 *             :公式所含量变量与可变参数所含变量不匹配
	 */
	public static String getFormulaValue(String myFormula,
			Map<String, String> argumentMap) {
		try {
			return new FooUtilsFomulaHelper(myFormula, argumentMap).getResult();
		} catch (NumberFormatException e) {
			System.out.println("BreakPoint-yunNan-公式中的变量名和传入Map参数中的变量名不匹配");
			return "0";
		}
	}

	public static String generateUUID() {
		return UUID.randomUUID().toString();
	}

	/**
	 * 格式化100000为100,000样式的字符串
	 * 
	 * @param number
	 * @return
	 */
	public static String getDecimalFormat(long number) {
		DecimalFormat dec = new DecimalFormat();
		dec.setGroupingUsed(true);
		dec.setGroupingSize(3);
		return dec.format(number);
	}

	/**
	 * 得到c不匹配周模式的ron表达式，例如56 20 11 26 7 ? 2013
	 * 
	 * @param myDateTime
	 * @return
	 */
	public static String getCronExpressionFromDateTime(DateTime myDateTime) {
		return "" + myDateTime.getSecondOfMinute() + " "
				+ myDateTime.getMinuteOfHour() + " " + myDateTime.getHourOfDay()
				+ " " + myDateTime.getDayOfMonth() + " "
				+ myDateTime.getMonthOfYear() + " ? " + myDateTime.getYear()
				+ "";
	}

	/**
	 * 得到oracle方言的时间查询片段，例如<br>
	 * <code>TO_DATE('2013-07-26 11:24:50','YYYY-MM-DD HH24:MI:SS')</code>
	 * 
	 * @param dateTime
	 * @return
	 */
	public static String getOracleSearchFragment(DateTime dateTime) {
		return "TO_DATE('" + FooUtils.toDateFromYear2Second(dateTime)
				+ "','YYYY-MM-DD HH24:MI:SS')";
	}

	/**
	 * Used in debug a business model
	 * 
	 * @param object
	 * @return
	 * @throws IntrospectionException
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 */
	public static String reflectToString(Object object) {
		return ReflectionToStringBuilder.toString(object);

		// if (object == null) {
		// return "objectIsNull";
		// }
		//
		// try {
		// StringBuilder sb = new StringBuilder();
		// sb.append(object.getClass().getName()).append("[");
		// for (Field field : object.getClass().getDeclaredFields()) {
		// PropertyDescriptor pd = new PropertyDescriptor(field.getName(),
		// object.getClass());
		// Method method = pd.getReadMethod();
		// sb.append(field.getName());
		// sb.append("=");
		// sb.append(method.invoke(object) == null ? "<null>" : method
		// .invoke(object).toString());
		// sb.append(",");
		// }
		// String result = sb.substring(0, sb.length() - 1) + "]";
		// return result;
		// } catch (Exception e) {
		// return "reflectObjectError";
		// }
	}

	/**
	 * 打印系统环境变量
	 */
	public static void printSystemEnv() {

		for (Entry<String, String> entry : System.getenv().entrySet()) {
			logger.info("Key:{},value:{}", entry.getKey(), entry.getValue());
		}

	}

	/**
	 * 打印系统环境变量
	 * 
	 * @return
	 */
	public static String getSystemDesktopPath() {
		return MoreObjects.firstNonNull(System.getenv("DESKTOP"),
				"C:\\Users\\Steve\\Desktop");
	}

	@Test
	public void testMain() throws IOException {

		File myDesDirectory = new File(getSystemDesktopPath());

		assertTrue("You should specify directory here",
				myDesDirectory.isDirectory());

		Collection<File> myFiles = FileUtils.listFiles(myDesDirectory,
				new String[] { "css" }, false);

		for (File file : myFiles) {
			logger.info(file.getName());
		}

	}

	/**
	 * 如果路径不存在就创建路径，如果存在则忽略该路径
	 * 
	 * @param fullFilePath
	 * @throws IOException
	 */
	public static void forceMkdir(String fullFilePath) throws IOException {

		File myFile = new File(fullFilePath);
		if (!myFile.isDirectory()) {
			logger.warn(
					"directory of:{} does not exist,we will create it for you.",
					fullFilePath);
			FileUtils.forceMkdir(myFile);
			return;
		}
		logger.info("directory of:{} already exist,we will jump.",
				fullFilePath);
	}

	/**
	 * 获得windows系统盘符，例如：D:
	 * 
	 * @param path
	 *            必须是包含盘符的路径
	 * @return
	 */
	public static String getWindowsDrivePartition(String path) {

		// String s1 = FilenameUtils.getFullPathNoEndSeparator(path);
		// String s2 = FilenameUtils.getPathNoEndSeparator(path);
		//
		// logger.trace("s1 is:{} and s2 is:{}", s1, s2);

		return FilenameUtils.getFullPathNoEndSeparator(path).substring(0, 2);

		// return FilenameUtils.getFullPathNoEndSeparator(path)
		// .replace(FilenameUtils.getPathNoEndSeparator(path), "")
		// .replaceAll("\\\\", "");
	}

	public static void cleanDirectory(File dir) throws IOException {
		if (dir == null || !dir.isDirectory()) {
			logger.error("your args of:{} is not a directory,just jump it.",
					dir);
			return;
		}
		FileUtils.cleanDirectory(dir);
	}

	public static void main2(String[] args)
			throws FileNotFoundException, IOException {

		String result = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE,
				"MmsStaffCanteen");

		System.out.println(StringUtils.replace(result, "_", "/"));

		FormFieldValidation[] validations = { FormFieldValidation.required,
				FormFieldValidation.mobile, };
		List<String> validationRulesDesc = Lists.newArrayList();
		for (FormFieldValidation tmp : validations) {
			if (tmp == null) {
				continue;
			}
			if (tmp != FormFieldValidation.empty) {
				validationRulesDesc.add(tmp.toString() + ":true");
			}
		}
		String eachFieldValidationDesc = "name:{"
				+ Joiner.on(",").join(validationRulesDesc) + "}";
		Map<String, Object> bean = Maps.newHashMap();
		bean.put("name", validations);

		logger.info("gson result:{}", eachFieldValidationDesc);

		// FileUtils.copyURLToFile(
		// new
		// URL("http://120.25.103.135:8088/open/images/sys/product/ads/02948299-9b35-4c7d-ab5a-579b48440851.jpg"),
		// new File("C:\\Users\\think\\Desktop\\test.jpg"));

		// System.out.println(DateTimeFormat.forPattern("HH:mm")
		// .parseDateTime("11:30").toDate());
		//
		// System.out.println(SystemUtils.IS_OS_WINDOWS);
		// System.out.println(SystemUtils.IS_OS_MAC);
		// System.out.println(SystemUtils.FILE_SEPARATOR);
		// System.out.println(SystemUtils.LINE_SEPARATOR);
		//
		// for (int i = 0; i < 5; i++) {
		// System.out.println(generateUUID());
		// }
		//
		// System.out.println(formatDouble(43026.29999999998));

		// System.out.println("industry-platform\\src\\main\\.gitignore".contains(".gitignore")
		// );
		//
		// String s = ("D:\\tmp");
		// System.out.println(FilenameUtils.getFullPath(s).replace(
		// FilenameUtils.getPath(s), ""));

		// String generatedJavaFileDirectory =
		// FooUtils.global_test_file_working_directory_str
		// + "\\autoGeneratedModel";
		//
		// forceMkdir(generatedJavaFileDirectory);
		//
		// IOUtils.write("fuck", new FileOutputStream(new File(
		// generatedJavaFileDirectory + "\\Fuck.java")), "utf-8");
		// System.out.println(" \"\" ");

		// System.out.println(extractIntegerFromString("varchar(2000)"));
		// System.out.println(StringUtils.capitalize("userId"));
		// System.out.println(Boolean.valueOf("true"));
		//
		// String myTableName = "app_attention";
		// String myClassName = CaseFormat.UPPER_UNDERSCORE.to(
		// CaseFormat.UPPER_CAMEL, myTableName.toUpperCase());
		// System.out.println(myClassName);

		// fooUtils .tttt="dddddddddddddd";
		// // String s = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL,
		// // "private_params");
		// Stopwatch stopwatch = Stopwatch.createStarted();
		//
		// String s = "123456";
		// // s = "123";
		// s.replaceAll("123", "");
		// System.out.println(s);
		//
		// TmpObject myObject = new TmpObject();
		// myObject.setGender("N");
		// myObject.setMyList(Lists.newArrayList(new TmpObject()));
		//
		// List<TmpObject> myList = Lists.newArrayList();
		// myList.add(new TmpObject());
		// myList.add(myObject);
		//
		// Map<String, Object> myMap = Maps.newLinkedHashMap();
		// myMap.put("status", "success");
		// myMap.put("breakdown", myList);
		// String result = new GsonBuilder().create().toJson(myMap);
		//
		// logger.info("result:{}", result);
		//
		// // printSystemEnv();
		// stopwatch.stop(); // optional
		// // long millis = stopwatch.elapsed(MILLISECONDS);
		// logger.info("time:{}", stopwatch.toString()); // formatted string
		// like
		// // "12.3 ms"

		// logger.info("no:{} and length:{},pass:{}", new Date().getTime(),
		// (new Date().getTime() + "").length(),
		// generateUUID().substring(0, 8));
		//
		// RandomDataGenerator randomData = new RandomDataGenerator();
		// for (int i = 0; i < 100; i++) {
		// logger.info("" + randomData.nextInt(100, 999));
		// }

	}

	public static File getClassPathResourceFile(String resourceName)
			throws IOException {
		return new ClassPathResource(resourceName).getFile();
	}

	public static InputStream getClassPathResourceInputStream(
			String resourceName) {
		try {
			return new ClassPathResource(resourceName).getInputStream();
		} catch (IOException e) {
			logger.error("error:{}", e);
		}
		return null;
	}

	public static Properties getPropertiesFromInputStream(
			InputStream inputStream) throws IOException {
		Properties p = new Properties();
		p.load(inputStream);
		return p;
	}

	public static Properties getPropertiesFromResourceFile(String resourceName)
			throws IOException {
		return getPropertiesFromInputStream(
				getClassPathResourceInputStream(resourceName));
	}

	public static Properties getPropertiesFromResourceFileSilent(
			String resourceName) {
		try {
			return getPropertiesFromInputStream(
					getClassPathResourceInputStream(resourceName));
		} catch (IOException e) {
			logger.error("resource file of:{} does not exist.", resourceName);
		}
		return null;
	}

	public static String generateCreateDatabaseSql(String databaseName) {
		return "CREATE DATABASE `" + databaseName
				+ "` DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci";
	}

	public static void main5(String[] args) {

		File tmpFile = new File(FileUtils.getTempDirectory()
				+ getFileSeparator() + generateUUID() + ".txt");

		logger.info("request tmpFile of:{}", tmpFile.getAbsolutePath());

		try {
			FileUtils.copyURLToFile(
					new URL("http://120.24.95.188/release-notes/latest.json"),
					tmpFile, 3000, 3000);

			String source = FileUtils.readFileToString(tmpFile);

			// List<Area> areas = gson.fromJson(source,
			// new TypeToken<List<Area>>() {
			// }.getType());
			CommonPatchRelease commonPatchRelease = getGson().fromJson(source,
					CommonPatchRelease.class);

			logger.info("success with:{}", commonPatchRelease.getCommitAcc());

		} catch (IOException e) {
			logger.error("{}", e);
		} finally {
			logger.info("clean tmpFile of:{} now.", tmpFile.getAbsolutePath());
			FileUtils.deleteQuietly(tmpFile);
		}

	}

	public static void main1(String[] args) {

		// System.out.println(new Date().getTime());
		//
		// for (int i = 0; i < 10; i++) {
		// System.out.println(getRandomUUID());
		// }
		//
		// String s = "\u7535\u4fe1\u5341\u56db";
		//
		// System.out.println(new String(s.getBytes("utf-8")));
		//
		// ClassPathResource myPath2 = new ClassPathResource(
		// "json/chrome-har.json");
		// String myString = IOUtils.toString(myPath2.getInputStream(),
		// "UTF-8");
		// System.out.println(myString);

		// 从excel解析数据,Start
		String myFileDirectory = "d:\\/tmp/";
		// String myResultFileName = "d:\\华为平台数据整理.xlsx";
		File myDirectory = new File(myFileDirectory);
		// File myFile = null;
		for (File file : myDirectory.listFiles()) {
			// System.out.println("Encounting file name of" + file.getName());
			if (file.isDirectory()) {
				System.out.println(
						"Encounting directory name of" + file.getName());
				continue;
			}
			try {
				OPCPackage pkg = OPCPackage
						.open(new File(myFileDirectory + file.getName()));
				XSSFWorkbook wb = new XSSFWorkbook(pkg);
				// XSSFWorkbook wb = new XSSFWorkbook();

				// System.out
				// .println("Start deal with excel of:" + file.getName());
				System.out.println(wb.getNumberOfSheets());
				for (int mySheet = 0; mySheet < wb
						.getNumberOfSheets(); mySheet++) {

					// Sheet sheet = wb.getSheetAt(mySheet);
					// 第一行为标题栏，跳过
				} // 结束所有工作表的读取
				pkg.close();
				System.out.println(
						"End deal with file name of:" + file.getName());
			} catch (Exception e) {
				System.out.println(
						"There's problem with file name of:" + file.getName());
				// e.printStackTrace();
			} finally {
			}
		}
	}

	public static String getJavaClassFieldTypeString(Field field) {

		String fieldTypeName = field.getType().getName();

		if (fieldTypeName.equals("java.util.Date")) {
			return "Date";
		} else if (fieldTypeName.equals("java.lang.String")) {
			return "String";
		} else if (fieldTypeName.equals("int")) {
			return "int";
		} else if (fieldTypeName.equals("double")) {
			return "double";
		} else if (fieldTypeName.equals("java.lang.Integer")) {
			return "int";
		} else {
			logger.error("error type on filed:{} for type:{}", field.getName(),
					fieldTypeName);
			throw new UnsupportedOperationException(
					"error type on field:" + field.getName());
		}
	}

	public static boolean IsMacOs() {
		return SystemUtils.IS_OS_MAC;
	}

	public static boolean IsWindowsOs() {
		return SystemUtils.IS_OS_WINDOWS;
	}

	/**
	 * return as：/Users/feiynn
	 * 
	 * @return
	 */
	public static String getUserHome() {
		return SystemUtils.getUserHome().toString();
	}

	/**
	 * return as:/Users/feiynn/Desktop
	 * 
	 * @return
	 */
	public static String getUserDesktopPath() {
		return SystemUtils.getUserHome().toString() + getFileSeparator()
				+ "Desktop";
	}

	/**
	 * 获得全局测试文件夹
	 * 
	 * @return
	 */
	public static String getGlobalAutoGeneratedDirectoryStr() {
		if (IsMacOs()) {
			return SystemUtils.getUserHome() + "/tmp/test/autoGenerated";
		}
		return "d:\\tmp\\test\\autoGenerated";
	}

	public static String getFileSeparator() {
		return SystemUtils.FILE_SEPARATOR;
	}

	/**
	 * execute command,support os-x and windows system only.
	 * 
	 * @param myCommand
	 * @return
	 * @throws IOException
	 */
	public static Process executeCommand(String myCommand) throws IOException {
		if (SystemUtils.IS_OS_MAC) {
			return Runtime.getRuntime()
					.exec(new String[] { "/bin/bash", "-c", myCommand });
		}
		return Runtime.getRuntime().exec(myCommand);
	}

	/**
	 * 
	 * @param scopes
	 *            用于模板的键值对，具体请参考Mustache文档
	 * @param template
	 *            以resources目录为根路径的模板地址，例如/myTmpl/myTmpl.jsp
	 * @return
	 * @throws Exception
	 */
	public static String generateDataWithMustache(Map<String, Object> scopes,
			String template) throws Exception {
		MustacheFactory mf = new DefaultMustacheFactory();
		Mustache mustache = mf.compile(template);
		Writer writer = new StringWriter();
		mustache.execute(writer, scopes);
		writer.flush();
		String result = writer.toString();
		return result;
	}

	/**
	 * Writes a String to a file creating the file if it does not exist. NOTE: As from v1.3, the parent directories of the file will be created if they do not exist.
	 * 
	 * @param file
	 *            the file to write
	 * @param data
	 *            the content to write to the file
	 * @throws IOException
	 */
	public static void writeStringToFile(File file, String data)
			throws IOException {
		FileUtils.writeStringToFile(file, data, Charset.forName("utf-8"));
	}

	/**
	 * Description 根据键值进行加密
	 * 
	 * @param data
	 * @param key
	 *            加密键byte数组
	 * @return
	 * @throws Exception
	 */
	public static String encrypt(String data) {
		try {
			Md5PasswordEncoder encoder = new Md5PasswordEncoder();
			String salt = key;
			return encoder.encodePassword(data, salt);
		} catch (Exception e) {
			logger.error("encrypt error here", e);
			return "";
		}
	}

	/**
	 * Description 根据键值进行解密
	 * 
	 * @param data
	 * @param key
	 *            加密键byte数组
	 * @return
	 * @throws IOException
	 * @throws Exception
	 */
	public static String decrypt(String data) throws IOException, Exception {
		if (data == null)
			return null;
		BASE64Decoder decoder = new BASE64Decoder();
		byte[] buf = decoder.decodeBuffer(data);
		byte[] bt = decrypt(buf, key.getBytes());
		return new String(bt);
	}

	/**
	 * Description 根据键值进行加密
	 * 
	 * @param data
	 * @param key
	 *            加密键byte数组
	 * @return
	 * @throws Exception
	 */
	public static byte[] encrypt(byte[] data, byte[] key) throws Exception {
		// 生成一个可信任的随机数源
		SecureRandom sr = new SecureRandom();

		// 从原始密钥数据创建DESKeySpec对象
		DESKeySpec dks = new DESKeySpec(key);

		// 创建一个密钥工厂，然后用它把DESKeySpec转换成SecretKey对象
		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
		SecretKey securekey = keyFactory.generateSecret(dks);

		// Cipher对象实际完成加密操作
		Cipher cipher = Cipher.getInstance(DES);

		// 用密钥初始化Cipher对象
		cipher.init(Cipher.ENCRYPT_MODE, securekey, sr);

		return cipher.doFinal(data);
	}

	/**
	 * Description 根据键值进行解密
	 * 
	 * @param data
	 * @param key
	 *            加密键byte数组
	 * @return
	 * @throws Exception
	 */
	private static byte[] decrypt(byte[] data, byte[] key) throws Exception {
		// 生成一个可信任的随机数源
		SecureRandom sr = new SecureRandom();

		// 从原始密钥数据创建DESKeySpec对象
		DESKeySpec dks = new DESKeySpec(key);

		// 创建一个密钥工厂，然后用它把DESKeySpec转换成SecretKey对象
		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
		SecretKey securekey = keyFactory.generateSecret(dks);

		// Cipher对象实际完成解密操作
		Cipher cipher = Cipher.getInstance(DES);

		// 用密钥初始化Cipher对象
		cipher.init(Cipher.DECRYPT_MODE, securekey, sr);

		return cipher.doFinal(data);
	}

}
